package client;

import com.fasterxml.jackson.databind.ObjectMapper;
import common.consts.Baidu;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import wrapper.baidu.GeoAdress;
import wrapper.baidu.GeoCoordinate;

import java.io.IOException;

/**
 * Created by aceyin on 15/7/9.
 */
@Component
public class BaiduClient {
    private static final Logger LOGGER = LoggerFactory.getLogger(BaiduClient.class);
    private static final ObjectMapper MAPPER = new ObjectMapper();

    /**
     * 根据经纬度反向查询地址信息
     *
     * @param lat
     * @param lng
     * @return
     */
    public GeoAdress address(double lat, double lng) {
        String url = getAddressApiURL(lat, lng);
        String ret = call(url);
        try {
            return MAPPER.readValue(ret, GeoAdress.class);
        } catch (IOException e) {
            LOGGER.error("Error while trying to parse JSON to object", e);
        }
        return null;
    }

    /**
     * 根据地址获取经纬度
     *
     * @param address
     * @return
     */
    public GeoCoordinate coordinate(String address) {
        String url = getCoordinateApiURL(address);
        String json = call(url);
        try {
            return MAPPER.readValue(json, GeoCoordinate.class);
        } catch (IOException e) {
            LOGGER.error("Error while trying to parse JSON to object", e);
        }
        return null;
    }

    private String call(String url) {
        CloseableHttpClient client = HttpClients.createDefault();
        HttpGet get = new HttpGet(url);
        try {
            CloseableHttpResponse response = client.execute(get);
            HttpEntity entity = response.getEntity();
            String ret = EntityUtils.toString(entity, "UTF-8");
            return ret;
        } catch (IOException e) {
            LOGGER.error("Error while trying to call BaiDu API", e);
        }
        return null;
    }

    /**
     * 根据地址查经纬度
     *
     * @param address
     * @return
     */
    private String getCoordinateApiURL(String address) {
        String api = Baidu.Geocoder.URL;
        Baidu.Geocoder.Param.Address2Coordinate[] params = Baidu.Geocoder.Param.Address2Coordinate.values();
        StringBuffer sb = new StringBuffer();
        for (Baidu.Geocoder.Param.Address2Coordinate param : params) {
            sb.append(param.name + "=" + param.value + "&");
        }
        String queryStr = sb.substring(0, sb.lastIndexOf("&"))
                .replaceAll("#ADDRESS", String.valueOf(address));
        return api + queryStr;
    }

    /**
     * 获取百度地图API反向查询的URL
     *
     * @param lat
     * @param lng
     * @return
     */
    private String getAddressApiURL(double lat, double lng) {
        String api = Baidu.Geocoder.URL;
        Baidu.Geocoder.Param.Coordinate2Address[] params = Baidu.Geocoder.Param.Coordinate2Address.values();
        StringBuffer sb = new StringBuffer();
        for (Baidu.Geocoder.Param.Coordinate2Address param : params) {
            sb.append(param.name + "=" + param.value + "&");
        }
        String queryStr = sb.substring(0, sb.lastIndexOf("&"))
                .replaceAll("#LAT", String.valueOf(lat))
                .replaceAll("#LNG", String.valueOf(lng));
        return api + queryStr;
    }
}
